/******************************************************************************
//             INTEL CORPORATION PROPRIETARY INFORMATION
//  This software is supplied under the terms of a license agreement or
//  nondisclosure agreement with Intel Corporation and may not be copied
//  or disclosed except in accordance with the terms of that agreement.
//    Copyright(c) 2000 - 2001 Intel Corporation. All Rights Reserved.
//
//  VSS: 
//     $Workfile: $
//     $Revision: $
//     $Date:     $
//     $Archive:  $
//
//  Description:
//      Intel(R) Integrated Performance Primitives - JPEG Helper file.
//      This file contains Forward DCT functions for multi-block processing. 
//
//  History:
//     Date         Author        Changes
//     2000/12/22  Jerry Hu       Created (Version 0.2, Multi-block processing)
//
********************************************************************************/
#include "_ippjpeg.h"

/*
// cos ((2*pi)/16) = 0.9238795325112867561
// cos ((6*pi)/16) = 0.3826834323650897717
// cos ((2*pi)/16) + cos ((6*pi)/16) = 
//                   1.3065629648763765278
// cos ((2*pi)/16) - cos ((6*pi)/16) = 
//                   0.5411961001461969844
*/

#define _SQRT2_2        2896  /* sqrt(2)/2 (15:23170)*/
#define _C_2A6_16       5352  /* cos ((2*pi)/16) + cos ((6*pi)/16) (15:42813)*/
#define _C_2S6_16       2217  /* cos ((2*pi)/16) - cos ((6*pi)/16) (15:17734)*/
#define _C_6_16         1567  /* cos ((6*pi)/16) (15:12540)*/

#define _CONSTFACTOR    12
#define _H_MP           2048
#define _V_MP           2048

/******************************************************************************
// Name:             ippiDCTQuantFwd_Blocks_JPEG_16s_I
// Description:      Performs Forward DCT and quantization for multi-block.
// Input Arguments: 
//          pSrcDst: Identifies source data in 8x8.
//       blockCount: Indicates the number of block in "pSrcDst".
//      pQuantTable: Identifies quantization table which was generated by
//                   ippiDCTQuantFwdTableInit_JPEG_16u32s.
//
// Output Arguments:
//          pSrcDst: Identifies destination data in 8x8.
//                  
// Remarks:      
//                   1. The start address of "pSrcDst" and  " pQuantTable"
//                      shall be aligned at 4byte boundary.
//                   2. It is better to do this alignment at 32byte boundary to optimize 
//                      D-Cache accessing.
//                   
// Returns:         
//    IPP_STATUS_OK: Succeeds.
//
******************************************************************************/
IPPFUN(IppStatus, ippiDCTQuantFwd_Blocks_JPEG_16s_I) (Ipp16s* pSrcDst, 
                                                     int   blockCount,
                                                     const Ipp16u *pQuantTable)
{
    int i, j;
    int c0,c1,c2,c3,c4,c5,c6,c7;
    int d0,d1,d2,d3,d4,d5,d6,d7;
    int e0, e1, e2, e3, a,b,c,d;
    int value, value1, value2;
    Ipp16s *pSrcDstCur;
    const Ipp16u *pQuantTableCur;

    _IPP_CHECK_ARG(NULL!=pSrcDst);
    _IPP_CHECK_ARG(_IPP_CHECK_ALIGN_4BYTE(pSrcDst));
    _IPP_CHECK_ARG(0<blockCount);
    _IPP_CHECK_ARG(NULL!=pQuantTable);
    _IPP_CHECK_ARG(_IPP_CHECK_ALIGN_4BYTE(pQuantTable));

    for (j=blockCount; j>0; j--) {

        pSrcDstCur=pSrcDst;
        pQuantTableCur=pQuantTable;
        /* Do 1D-DCT in the each row */
        for (i=8; i>0; i--) {

            c0=pSrcDstCur[0]+pSrcDstCur[7];
            c1=pSrcDstCur[1]+pSrcDstCur[6];
            c2=pSrcDstCur[2]+pSrcDstCur[5];
            c3=pSrcDstCur[3]+pSrcDstCur[4];
            c4=pSrcDstCur[3]-pSrcDstCur[4];
            c5=pSrcDstCur[2]-pSrcDstCur[5];
            c6=pSrcDstCur[1]-pSrcDstCur[6];
            c7=pSrcDstCur[0]-pSrcDstCur[7];

            e0=c0+c3;
            e1=c1+c2;
            e2=c1-c2;
            e3=c0-c3;

            pSrcDstCur[0]=(Ipp16s)(e0+e1);
            pSrcDstCur[4]=(Ipp16s)(e0-e1);
    
            value=((e2+e3)*_SQRT2_2+_H_MP)>>_CONSTFACTOR;
            pSrcDstCur[2]=(Ipp16s)(e3+value);
            pSrcDstCur[6]=(Ipp16s)(e3-value);

            a=c4+c5;
            b=c5+c6;
            c=c6+c7;
            d=c7;

            value1=b*_SQRT2_2;

            value2=(a-c)*_C_6_16;
            value=c*_C_2A6_16+value2;
    
            pSrcDstCur[1]=(Ipp16s)(d+((value1+value+_H_MP)>>_CONSTFACTOR));
            pSrcDstCur[7]=(Ipp16s)(d+((value1-value+_H_MP)>>_CONSTFACTOR));

            value=a*_C_2S6_16+value2;    

            pSrcDstCur[5]=(Ipp16s)(d-((value1-value+_H_MP)>>_CONSTFACTOR));
            pSrcDstCur[3]=(Ipp16s)(d-((value1+value+_H_MP)>>_CONSTFACTOR));

            pSrcDstCur+=8;
        }

        pSrcDstCur=pSrcDst;

        /* Do 1D-DCT in the each col */
        for (i=8; i>0; i--) {

            c0=pSrcDstCur[0*8]+pSrcDstCur[7*8];
            c1=pSrcDstCur[1*8]+pSrcDstCur[6*8];
            c2=pSrcDstCur[2*8]+pSrcDstCur[5*8];
            c3=pSrcDstCur[3*8]+pSrcDstCur[4*8];
            c4=pSrcDstCur[3*8]-pSrcDstCur[4*8];
            c5=pSrcDstCur[2*8]-pSrcDstCur[5*8];
            c6=pSrcDstCur[1*8]-pSrcDstCur[6*8];
            c7=pSrcDstCur[0*8]-pSrcDstCur[7*8];

            e0=c0+c3;
            e1=c1+c2;
            e2=c1-c2;
            e3=c0-c3;

            d0=e0+e1;
            d4=e0-e1;
    
            value=((e2+e3)*_SQRT2_2+_V_MP)>>_CONSTFACTOR;
            d2=e3+value;
            d6=e3-value;

            a=c4+c5;
            b=c5+c6;
            c=c6+c7;
            d=c7;

            value1=b*_SQRT2_2;

            value2=(a-c)*_C_6_16;
            value=c*_C_2A6_16+value2;
    
            d1=d+((value1+value+_V_MP)>>_CONSTFACTOR);
            d7=d+((value1-value+_V_MP)>>_CONSTFACTOR);

            value=a*_C_2S6_16+value2;    

            d5=d-((value1-value+_V_MP)>>_CONSTFACTOR);
            d3=d-((value1+value+_V_MP)>>_CONSTFACTOR);

            pSrcDstCur[0*8]=(Ipp16s)((d0*pQuantTableCur[0]+16384)>>15);
            pSrcDstCur[1*8]=(Ipp16s)((d1*pQuantTableCur[1]+16384)>>15);
            pSrcDstCur[2*8]=(Ipp16s)((d2*pQuantTableCur[2]+16384)>>15);
            pSrcDstCur[3*8]=(Ipp16s)((d3*pQuantTableCur[3]+16384)>>15);
            pSrcDstCur[4*8]=(Ipp16s)((d4*pQuantTableCur[4]+16384)>>15);
            pSrcDstCur[5*8]=(Ipp16s)((d5*pQuantTableCur[5]+16384)>>15);
            pSrcDstCur[6*8]=(Ipp16s)((d6*pQuantTableCur[6]+16384)>>15);
            pSrcDstCur[7*8]=(Ipp16s)((d7*pQuantTableCur[7]+16384)>>15);

            pSrcDstCur++;
            pQuantTableCur+=8;
        }
        pSrcDst+=64;
    }
    return IPP_STATUS_OK;
}

/******************************************************************************
// Name:             ippiDCTQuantFwd_Blocks_JPEG_16s
// Description:      Performs Forward DCT and quantization for multi-block.
// Input Arguments: 
//          pSrcDst: Identifies source data in 8x8.
//       blockCount: Indicates the number of block in "pSrcDst".
//      pQuantTable: Identifies quantization table which was generated by
//                   ippiDCTQuantFwdTableInit_JPEG_16u32s.
//
// Output Arguments:
//          pSrcDst: Identifies destination data in 8x8.
//                  
// Remarks:      
//                   1. The start address of "pSrc", "pDst" and "pQuantTable"
//                      shall be aligned at 4byte boundary.
//                   2. It is better to do this alignment at 32byte boundary to optimize 
//                      D-Cache accessing.
//                   
// Returns:         
//    IPP_STATUS_OK: Succeeds.
//
******************************************************************************/
IPPFUN(IppStatus, ippiDCTQuantFwd_Blocks_JPEG_16s) (const Ipp16s* pSrc, 
                                                   Ipp16s *pDst, 
                                                   int   blockCount,
                                                   const Ipp16u *pQuantTable)
{
    int i,j;
    int c0,c1,c2,c3,c4,c5,c6,c7;
    int d0,d1,d2,d3,d4,d5,d6,d7;
    int e0, e1, e2, e3, a,b,c,d;
    int value, value1, value2;
    Ipp16s *pTempPtr, *pDstCur;
    const Ipp16s *pSrcCur;
    const Ipp16u *pQuantTableCur;

    _IPP_CHECK_ARG(NULL!=pSrc);
    _IPP_CHECK_ARG(_IPP_CHECK_ALIGN_4BYTE(pSrc));
    _IPP_CHECK_ARG(NULL!=pDst);
    _IPP_CHECK_ARG(_IPP_CHECK_ALIGN_4BYTE(pDst));
    _IPP_CHECK_ARG(0<blockCount);
    _IPP_CHECK_ARG(NULL!=pQuantTable);
    _IPP_CHECK_ARG(_IPP_CHECK_ALIGN_4BYTE(pQuantTable));

    for (j=blockCount; j>0; j--) {

        pSrcCur=pSrc;
        pDstCur=pDst;
        pTempPtr=pDst;
        pQuantTableCur=pQuantTable;

        /* Do 1D-DCT in the each row */
        for (i=8; i>0; i--) {

            c0=pSrcCur[0]+pSrcCur[7];
            c1=pSrcCur[1]+pSrcCur[6];
            c2=pSrcCur[2]+pSrcCur[5];
            c3=pSrcCur[3]+pSrcCur[4];
            c4=pSrcCur[3]-pSrcCur[4];
            c5=pSrcCur[2]-pSrcCur[5];
            c6=pSrcCur[1]-pSrcCur[6];
            c7=pSrcCur[0]-pSrcCur[7];

            e0=c0+c3;
            e1=c1+c2;
            e2=c1-c2;
            e3=c0-c3;

            pTempPtr[0]=(Ipp16s)(e0+e1);
            pTempPtr[4]=(Ipp16s)(e0-e1);
    
            value=((e2+e3)*_SQRT2_2+_H_MP)>>_CONSTFACTOR;
            pTempPtr[2]=(Ipp16s)(e3+value);
            pTempPtr[6]=(Ipp16s)(e3-value);

            a=c4+c5;
            b=c5+c6;
            c=c6+c7;
            d=c7;

            value1=b*_SQRT2_2;

            value2=(a-c)*_C_6_16;
            value=c*_C_2A6_16+value2;
    
            pTempPtr[1]=(Ipp16s)(d+((value1+value+_H_MP)>>_CONSTFACTOR));
            pTempPtr[7]=(Ipp16s)(d+((value1-value+_H_MP)>>_CONSTFACTOR));

            value=a*_C_2S6_16+value2;    

            pTempPtr[5]=(Ipp16s)(d-((value1-value+_H_MP)>>_CONSTFACTOR));
            pTempPtr[3]=(Ipp16s)(d-((value1+value+_H_MP)>>_CONSTFACTOR));

            pSrcCur+=8;
            pTempPtr+=8;
        }

        pTempPtr=pDstCur;

        /* Do 1D-DCT in the each col */
        for (i=8; i>0; i--) {

            c0=pTempPtr[0*8]+pTempPtr[7*8];
            c1=pTempPtr[1*8]+pTempPtr[6*8];
            c2=pTempPtr[2*8]+pTempPtr[5*8];
            c3=pTempPtr[3*8]+pTempPtr[4*8];
            c4=pTempPtr[3*8]-pTempPtr[4*8];
            c5=pTempPtr[2*8]-pTempPtr[5*8];
            c6=pTempPtr[1*8]-pTempPtr[6*8];
            c7=pTempPtr[0*8]-pTempPtr[7*8];

            e0=c0+c3;
            e1=c1+c2;
            e2=c1-c2;
            e3=c0-c3;

            d0=e0+e1;
            d4=e0-e1;
    
            value=((e2+e3)*_SQRT2_2+_V_MP)>>_CONSTFACTOR;
            d2=e3+value;
            d6=e3-value;

            a=c4+c5;
            b=c5+c6;
            c=c6+c7;
            d=c7;

            value1=b*_SQRT2_2;

            value2=(a-c)*_C_6_16;
            value=c*_C_2A6_16+value2;
    
            d1=d+((value1+value+_V_MP)>>_CONSTFACTOR);
            d7=d+((value1-value+_V_MP)>>_CONSTFACTOR);

            value=a*_C_2S6_16+value2;    

            d5=d-((value1-value+_V_MP)>>_CONSTFACTOR);
            d3=d-((value1+value+_V_MP)>>_CONSTFACTOR);

            pDstCur[0*8]=(Ipp16s)((d0*pQuantTableCur[0]+16384)>>15);
            pDstCur[1*8]=(Ipp16s)((d1*pQuantTableCur[1]+16384)>>15);
            pDstCur[2*8]=(Ipp16s)((d2*pQuantTableCur[2]+16384)>>15);
            pDstCur[3*8]=(Ipp16s)((d3*pQuantTableCur[3]+16384)>>15);
            pDstCur[4*8]=(Ipp16s)((d4*pQuantTableCur[4]+16384)>>15);
            pDstCur[5*8]=(Ipp16s)((d5*pQuantTableCur[5]+16384)>>15);
            pDstCur[6*8]=(Ipp16s)((d6*pQuantTableCur[6]+16384)>>15);
            pDstCur[7*8]=(Ipp16s)((d7*pQuantTableCur[7]+16384)>>15);

            pTempPtr++;
            pDstCur++;
            pQuantTableCur+=8;
        }
        pSrc+=64;
        pDst+=64;
    }
    return IPP_STATUS_OK;
}



/* EOF */
